<template>
<div class="col-md-12">
  <div class="col-md-8" id="lcdbg">
  </div>
  <div class="col-md-4" v-for="banner in banners" v-show="selectedIndex === $index">
    <form class="form-horizontal">
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.postion')}}</label>
        <div class="col-sm-2">
          <input type="text" class="form-control" v-model="banner.showRect.left" readonly>
        </div>
        <div class="col-sm-2">
          <input type="text" class="form-control" v-model="banner.showRect.right" readonly>
        </div>
        <div class="col-sm-2">
          <input type="text" class="form-control" v-model="banner.showRect.top" readonly>
        </div>
        <div class="col-sm-2">
          <input type="text" class="form-control" v-model="banner.showRect.bottom" readonly>
        </div>
      </div>
      <hr /> 
      <div class="form-group">
        <div class="col-sm-offset-3 col-sm-4">
          <div class="checkbox">
            <label>
              <input type="checkbox" v-model="banner.text.show" :true-value=1 :false-value=0> {{$t('lcd.showTitle')}}
            </label>
          </div>
        </div>
        <div class="col-sm-4">
          <div class="checkbox">
            <label>
              <input type="checkbox" v-model="banner.scroll.enable" :true-value=1 :false-value=0 @change="onBannerScrollEnableChange(banner)"> {{$t('lcd.scrollEnable')}}
            </label>
          </div>
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.scrollInterval')}}</label>
        <div class="col-sm-9">
          <input type="range" class="form-control" v-model="banner.scroll.interval" min="60" max="150" step="10">
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.title')}}</label>
        <div class="col-sm-9">
          <input type="text" class="form-control" v-model="banner.text.content" maxlength="64">
        </div>
      </div> 
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.color')}}</label>
        <div class="col-sm-9">
          <vc-slider :colors.sync="banner._tmp.color"></vc-slider>
        </div>
      </div>
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.fontSize')}}</label>
        <div class="col-sm-9">
          <input type="range" class="form-control" v-model="banner.text.fontSize" min="20" max="200" step="5">
        </div>
      </div>  
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.alignHorizontal')}}</label>
        <div class="col-sm-9">
          <select class="form-control" v-model="banner.text.align" :disabled="banner.scroll.enable === 1">
            <option v-for="option in alignOptions" :value="option.value">{{option.text}}</option>
          </select>
        </div>
      </div> 
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.alignVertical')}}</label>
        <div class="col-sm-9">
          <select class="form-control" v-model="banner.text.alignV">
            <option v-for="option in alignVOptions" :value="option.value">{{option.text}}</option>
          </select>
        </div>
      </div>             
      <hr /> 
      <div class="form-group">
        <div class="col-sm-offset-3 col-sm-9">
          <div class="checkbox">
            <label>
              <input type="checkbox" v-model="banner.background.show" :true-value=1 :false-value=0> {{$t('lcd.bgEnable')}}
            </label>
          </div>
        </div>
      </div>     
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.color')}}</label>
        <div class="col-sm-9">
          <vc-slider :colors.sync="banner._tmp.bgColor"></vc-slider>
        </div>
      </div> 
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.opacity')}}</label>
        <div class="col-sm-9">
          <input type="range" class="form-control" v-model="banner.background.opacity" min="0" max="100" step="1">
        </div>
      </div>
      <div class="form-group">
        <div class="col-sm-offset-3 col-sm-9">
          <button type="button" class="btn btn-default" @click.prevent="onClearImg(banner)">{{$t('lcd.clearImg')}}</button>
        </div>
      </div> 
      <div class="form-group">
        <label class="col-sm-3 control-label">{{$t('lcd.image')}}</label>
        <div class="col-sm-9">
        <div class="input-group"> 
          <input type="text" class="form-control" v-model="banner._tmp.fileName" readonly>
          <span class="input-group-btn">
            <span class="btn btn-primary btn-file">
              {{ $t("common.browse") }}&hellip;
              <input type="file" @change.prevent="onImgChange" :accept="accept">
            </span>
          </span>
        </div>
        </div>
      </div>
      <div class="form-group">
        <div class="col-sm-offset-3 col-sm-4">
          <button type="button" class="btn btn-default" @click.prevent="onSubmit">{{ $t("common.upload") }}</button>
        </div>
        <div class="col-sm-4">
          <button type="button" class="btn btn-default" @click.prevent="onScroll">{{ $t("common.scroll") }}</button>
        </div>
      </div>
    </form>    
  </div>
</div>
</template>

<script>
import async from 'async'
import toast from 'libs/toast.js'
import msgbox from 'libs/msgbox.js'
import ebus from 'libs/ebus.js'
import {LcdPreview} from 'libs/canvas.js'
import dftBanner from './dftBanner.js'
import {http} from 'share/common/api.js'
import dftBannerForDev from './dftBannerForDev.js'
import {printObj, readableSize, calRectCross, calRelativeRect} from 'libs/utils.js'

export default {
  props: {
    accept: {
      type: String,
      default: 'image/jpeg,image/png,image/bmp'
    },
    multiScreen: {
      type: Object,
      default: function() {
        return {
          x: 1,
          y: 1
        }
      }
    },
    doSubmit: {
      type: Function,
      required: true
    }
  },
  data: function() {
    return {
      selectedIndex: -1, 
      banners: [],
      alignOptions: [{
        value: 'left',
        text: this.$t('lcd.left')
      }, {
        value: 'center',
        text: this.$t('lcd.center')
      }, {
        value: 'right',
        text: this.$t('lcd.right')
      }],
      alignVOptions: [{
        value: 'top',
        text: this.$t('lcd.top')
      }, {
        value: 'center',
        text: this.$t('lcd.center')
      }, {
        value: 'bottom',
        text: this.$t('lcd.bottom')
      }]
    }
  },
  computed: {
    width () {
      return 1280 * this.multiScreen.x
    },
    height () {
      return 720 * this.multiScreen.y
    }
  },
  methods: { 
    onBannerScrollEnableChange (banner) {
      banner.text.align = 'left'
    },
    makeBannerTextCmdParamlist (screen, banner, bannerIndex) {
      let bannerRect = banner.showRect
      let cross = calRectCross(screen.rect, bannerRect)
      if (!cross) {
        return null
      }

      var paramlist = {
        index: bannerIndex,
        color: banner.text.color,
        align: banner.text.align,
        alignV: banner.text.alignV,
        text: {
          fontName: banner.text.fontName,
          fontSize: banner.text.fontSize,
          rect: calRelativeRect(bannerRect, cross),   
          content: banner.text.content,
        },
        banner: {
          totalWidth: bannerRect.right - bannerRect.left,
          totalHeight: bannerRect.bottom - bannerRect.top,
          show: 1,
          showRect: calRelativeRect(screen.rect, cross)   
        }         
      }  
      return paramlist   
    },
    sendDevCmd (decoder, uri, cmd) {
      let host = `http://${decoder.ipaddr}:7080`
      return http(host, uri, 'POST', cmd)
    },
    updateScrollParamlist (decoder) {
      var textRect = decoder.paramlist.text.rect
      if (textRect.left + 3 <= decoder.scrollLength) {
        textRect.left += 3
        textRect.right += 3
      } else {
        textRect.left = decoder.textInitLeft
        textRect.right = decoder.textInitRight
      }
    },
    doScroll () {
      let decoders = this.lcdInfo.decoders
      let banner = this.banners[this.selectedIndex]

      _.forEach(decoders, function(decoder) {
        if (!decoder.ipaddr || !decoder.paramlist) {
          return
        }       
        this.updateScrollParamlist(decoder)
        this.sendDevCmd(decoder, '/dev/multimedia/cmd', {
          action: 'setBannerText',
          paramlist: decoder.paramlist
        })
      }.bind(this))
    },
    doStartScroll () {
      var decoders = this.lcdInfo.decoders
      let screens = this.makeScreens()
      let banner = this.banners[this.selectedIndex]
      let bannerRect = banner.showRect
      let bannerWidth = bannerRect.right - bannerRect.left

      _.forEach(decoders, function(decoder) {
        decoder.screen = screens[decoder.index]
        decoder.paramlist = this.makeBannerTextCmdParamlist(decoder.screen, 
          banner, 
          this.selectedIndex)
        if (decoder.paramlist) {
          decoder.scrollLength = banner.scroll.textWidth + 10 + decoder.paramlist.text.rect.left           
          decoder.textInitLeft = decoder.paramlist.text.rect.left - bannerWidth
          decoder.textInitRight = decoder.paramlist.text.rect.right - bannerWidth
        }
      }.bind(this))

      let timer = setInterval(this.doScroll, banner.scroll.interval)
      msgbox.alert({
        title: this.$t('alert.plzWait'),
        text: this.$t('alert.autoSwitch'),
        type: "info",
        showCancelButton: false,
        confirmButtonColor: "#DD6B55",
        confirmButtonText: this.$t('common.stop'),
        closeOnConfirm: true
      }, 
      function() {
        clearInterval(timer)
      }) 
    },
    startScroll () {
      let decoders = this.lcdInfo.decoders

      async.each(decoders, function(decoder, callback) {
        if (!decoder.ipaddr) {
          callback()
          return
        }    
            
        this.sendDevCmd(decoder, '/api/auth/login', {
          username: 'api',
          password: 'api'
        }).then(function(res) {
          if (res && res.data && res.data.code === 0) {
            callback()
          } else {
            callback({msg: `code[${res.data.code}]`})
          }
        }, function(res) {
          callback({msg: 'error'})
        })
      }.bind(this), function(err) {
        if (err) {
          toast.e(this, this.$t('common.fail'), err.msg)
        } else {
          this.doStartScroll()
        }
      }.bind(this))      
    },
    onScroll () {
      let banner = this.banners[this.selectedIndex]
      if (!banner.scroll.enable) {
        toast.e(this, this.$t('common.fail'), this.$t('error.notEnable'))
        return
      }

      this.startScroll()
    },
    makeScreens () {
      let total = this.multiScreen.x * this.multiScreen.y
      var screens = []
      var index = 0

      for (var y = 0; y < this.multiScreen.y; y++) {
        for (var x = 0; x < this.multiScreen.x; x++) {
          screens.push({
            index,
            rect: {
              left: x * 1280,
              top: y * 720,
              right: (x + 1) * 1280,
              bottom: (y + 1) * 720
            }
          })
          index++
        }
      }

      return screens      
    },
    makeBannerImage (stage, area) {
      let dataUrl = stage.toDataURL({
        mimeType: 'image/png',
        quality: 0.8,
        x: area.x,
        y: area.y,
        width: area.width,
        height: area.height         
      }) 

      return dataUrl
    },
    makeLcdBannerImage (lcdbanner, banner) {
      function getAreaOfBanner(group) {
        let image = group.find('Image')[0]
        return {
          x: group.x(),
          y: group.y(),
          width: image.width(),
          height: image.height()
        }
      }

      if (banner._tmp.img === null) {
        return ''
      }

      let stage = lcdbanner.stage
      let group = stage.find('.banner')[0]
      let area = getAreaOfBanner(group)
      lcdbanner.setBannerBgVisible(group, false)
      let imageDataURL = this.makeBannerImage(stage, area) 
      lcdbanner.setBannerBgVisible(group, true)
      return imageDataURL
    },
    makeScreenBannerImage (lcdbanner, banner, cross) {
      if (banner.background.show !== 1) {
        return ''
      }

      let stage = lcdbanner.stage
      let group = stage.find('.banner')[0]
      let area = {
        x: cross.left,
        y: cross.top,
        width: cross.right - cross.left,
        height: cross.bottom - cross.top
      }
      return this.makeBannerImage(stage, area)
    },
    makeScreenBanner (lcdbanner, banner, screen) {
      let bannerRect = banner.showRect
      let cross = calRectCross(screen.rect, bannerRect)
      if (cross) {
        var bannerForDev = {
          background: {
            rect: calRelativeRect(bannerRect, cross),
            image: this.makeScreenBannerImage(lcdbanner, banner, cross),
            show: banner.background.show
          },
          text: {
            color: banner.text.color,
            align: banner.text.align,
            alignV: banner.text.alignV,
            text: {
              fontName: banner.text.fontName,
              fontSize: banner.text.fontSize,
              rect: calRelativeRect(bannerRect, cross),   
              content: banner.text.content,
            },
            show: banner.text.show
          },
          banner: {
            totalWidth: bannerRect.right - bannerRect.left,
            totalHeight: bannerRect.bottom - bannerRect.top,
            showRect: calRelativeRect(screen.rect, cross)   
          }          
        }
        return bannerForDev
      } else {
        return dftBannerForDev
      }
    },
    recordBanner (lcdbanner, banners) {
      async.eachOfSeries(banners, function(banner, index, callback) {
        var singleBanners = [banner]
        lcdbanner.updateBanners(singleBanners)
        banner.scroll.textWidth = banner._tmp.textWidth
        banner.background.image = this.makeLcdBannerImage(lcdbanner, banner)

        let stage = lcdbanner.stage
        let group = stage.find('.banner')[0]
        let screens = this.makeScreens()
        _.forEach(screens, function (screen) {
          banner._tmp.screens.push(this.makeScreenBanner(lcdbanner, banner, screen))
        }.bind(this))

        callback()
      }.bind(this), function(err) {

      })
    },
    checkBannersCross () {
      var crossCnt = 0
      for (var i = 0; i < this.banners.length; i++) {
        for (var j = i + 1; j < this.banners.length; j++) {
          let cross = calRectCross(this.banners[i].showRect, this.banners[j].showRect)
          if (cross) {
            console.log(`banner cross with [${i + 1}] and [${j + 1}]`)
            crossCnt++
          }
        }
      }
      return crossCnt > 0
    },
    onClearImg (banner) {
      banner._tmp.fileName = ''
      banner._tmp.img = ''
    },
    onSubmit () {
      //底层不支持图层，无法支持横幅之间叠加
      if (this.checkBannersCross()) {
        toast.e(this, this.$t('common.fail'), this.$t('error.notSupport'))
        return
      }
      var offContainer = document.createElement("div")
      var lcdbanner = new LcdPreview()
      lcdbanner.init(offContainer, {
        width: this.width,
        height: this.height,
        scale: 1 
      })

      _.forEach(this.banners, (banner) => {
        banner.text.color = banner._tmp.color.hex
        banner.background.bgColor = banner._tmp.bgColor.hex
        banner._tmp.preview = false
        banner._tmp.screens = []
      })

      this.recordBanner(lcdbanner, this.banners)
      lcdbanner.uninit()

      _.forEach(this.banners, (banner) => {
        Object.defineProperty(banner, '_tmp', {
          enumerable: false
        })
      })

      this.doSubmit(this.banners, function() {
        //do nothing
      })
    },
    onAddBanner () {
      this.banners.push(this.banner)
      this.preview.addBanner(this.banner)
    },
    onImgChange (e) {
      let file = e.target.files[0]
      var banner = this.banners[this.selectedIndex]
      banner._tmp.fileName = file.name
      var reader = new FileReader()
      reader.onload = function(e) {
        var image = new Image()
        image.src = e.target.result
        image.onload = function(e) {
          banner._tmp.img = image
          banner.background.show = 1
        }
      }
      reader.readAsDataURL(file)     
    },
    onBannerChange () {
      this.preview.updateBanner(this.selectedIndex)
    },
    updateBackground () {
      _.forEach(this.banners, function(banner, index) {
        let background = banner.background
        if (background.image.startsWith('data:image/')) {
          var image = new Image()
          image.src = background.image
          image.onload = function() {
            banner._tmp.img = image
            this.preview.updateBanner(index)
          }.bind(this)
        }
      }.bind(this))
    },
    resetPreview () {
      this.preview.updateBanners(this.banners)
      this.updateBackground()
    },
    drawPreview (params) {
      let banners = params.banners
      this.lcdInfo = params.lcd
      let showWidth = window.innerWidth * 5 / 8
      this.scale = showWidth / this.width
      this.preview.init('lcdbg', {
        width: this.width * this.scale,
        height: this.height * this.scale,
        scale: this.scale    
      })
      this.preview.updateBg({
        color: {
          hex: '#DDD'
        }
      })
      this.preview.setMultiScreen(this.multiScreen)
      var currBanners = []
      if (banners && banners.length > 0) {
        currBanners = banners
      } else {
        currBanners = this.createDftBanners()
      }
      _.forEach(currBanners, function(banner, index) {
        if ((typeof banner.background.bgColor == 'undefined') 
          || (typeof banner.background.opacity == 'undefined')) {
          banner.background.bgColor = '#4095BF'
          banner.background.opacity = 50
        }
        banner._tmp = {
          onSelect: function () {
            this.selectedIndex = index
          }.bind(this),
          fileName: '',
          img: null,
          color: {
            hex: ''
          },
          bgColor: {
            hex: ''
          },
          index,
          textWidth: 0,
          preview: true
        }
        banner._tmp.color.hex = banner.text.color
        banner._tmp.bgColor.hex = banner.background.bgColor
      }.bind(this))
      this.banners = currBanners
      this.selectedIndex = 0 
      this.preview.updateBanners(this.banners)
      this.updateBackground()
    },
    createDftBanners () {
      var banners = []
      let height = dftBanner.showRect.bottom - dftBanner.showRect.top
      for (var i = 0; i < 5; i++) {
        var banner = _.cloneDeep(dftBanner)
        banner.showRect.top +=  height * i
        banner.showRect.bottom +=  height * i
        banner.text.content += `[${i+1}]`
        banners.push(banner)
      }

      return banners
    }
  },
  ready () {
    this.preview = new LcdPreview()
    ebus.on('reset-lcdbg', this.resetPreview)
    ebus.on('draw-preview', this.drawPreview)
    this.$watch('banners', this.onBannerChange, {deep: true})
  },
  beforeDestroy() {
    this.preview.uninit()
  }
}
</script>

<style>
.btn-file {
  position: relative;
  overflow: hidden;
}
.btn-file input[type=file] {
  position: absolute;
  top: 0;
  right: 0;
  min-width: 100%;
  min-height: 100%;
  font-size: 100px;
  text-align: right;
  filter: alpha(opacity=0);
  opacity: 0;
  background: red;
  cursor: inherit;
  display: block;
}
input[readonly] {
  background-color: white !important;
  cursor: text !important;
}
</style>